package earogya.ehr.patient_details;

import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import earogya.util.PatientDetailsHibernateUtil;;


/**
 * 
 * Manage the access to Database
 * 
 * @author Ureka
 *
 */
public class HibernateManager {
	
	public HibernateManager(){
	}
	
	
	/**
	 * 
	 * Save an object to database
	 * 
	 * @param obj
	 * @return object id in the database
	 * @throws HibernateException
	 */
	public int saveObject(Object obj) throws HibernateException{
		Integer id=0;
		try{
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
			
		session.beginTransaction();
			id=(Integer)session.save(obj);
			session.getTransaction().commit();
		}catch(HibernateException e){
				throw e;
			}
		return id;
	}
	
	
	/**
	 * 
	 * Save list of objects to database
	 * 
	 * @param objList
	 * @throws HibernateException
	 */
	public void saveObjectList(List<Object> objList) throws HibernateException{
		
		try{
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
			for(int i=0;i<objList.size();i++){
		session.beginTransaction();
			session.save(objList.get(i));
			session.getTransaction().commit();
			}
		}catch(HibernateException e){
				throw e;
			}
		
	}
	
	
	/**
	 * 
	 * Query a list of values of a required field from the databse
	 * 
	 * @param fieldsAndValues
	 * @param required_field
	 * @param className
	 * @param objectName
	 * @return list of objects
	 */
	public List queryValueListFromDatabase(Object[][] fieldsAndValues, String required_field, String className, String objectName) throws HibernateException{
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
		List list=null;
			session.beginTransaction();
			Query query=session.createQuery(this.buildSelectQuery(fieldsAndValues, required_field, className, objectName));
	        list=query.list();
		return list;
	}	
	
	
	/**
	 * 
	 * Query a list of values of list of required fields from the database
	 * 
	 * @param fieldsAndValues
	 * @param required_field
	 * @param className
	 * @param objectName
	 * @return object list
	 */
	public List queryValueListFromDatabase(Object[][] fieldsAndValues, String[] required_field, String className, String objectName) throws HibernateException{
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
		List list=null;
			session.beginTransaction();
			Query query=session.createQuery(this.buildSelectQuery(fieldsAndValues, required_field, className, objectName));
	        list=query.list();
	        return list;
	}
	
	/**
	 * Creates an sql query using the given information.
	 * @param fieldsAndValues - name of the columns and their respective values
	 * @param required_field - name of the required column 
	 * @param table - name of the table
	 * @return
	 */
	private String buildSelectQuery(Object[][] fieldsAndValues, String[] required_field, String className, String objectName) throws HibernateException{
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT ");
		for(int i=0; i<required_field.length; i++){
			if(i<required_field.length-1){
				builder.append(objectName+"."+required_field[i]+", ");
			}
			else{
				builder.append(objectName+"."+required_field[i]+" FROM "+className+" AS "+objectName+" WHERE ");
			}
		}
		int j=0;
		for(int i=0; i<fieldsAndValues.length; i++){
			
			if(fieldsAndValues[i][1]!=null){
			if(j==0){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}else{
				builder.append(" AND "+objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
			j++;
			}
		}
		return builder.toString();
	}
	
	/**
	 * Creates an sql query using the given information.
	 * @param fieldsAndValues - name of the columns and their respective values
	 * @param required_field - name of the required column 
	 * @param table - name of the table
	 * @return
	 */
	private String buildSelectQuery(Object[][] fieldsAndValues, String required_field, String className, String objectName) throws HibernateException{
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT "+objectName+"."+required_field+" FROM "+className+" AS "+objectName+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(objectName+"."+fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}

	
	/**
	 * 
	 * create a select all query using the given information
	 * 
	 * @param fieldsAndValues
	 * @param table
	 * @return select all query
	 */
	public String buildSelectAllQuery(Object[][] fieldsAndValues, String table) throws HibernateException{
		StringBuilder builder=new StringBuilder();
		builder.append("SELECT {patient.*} FROM "+table+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}	

	/**
	 * 
	 * Build the delete query based on the given information
	 * 
	 * @param fieldsAndValues
	 * @param table
	 * @return delete query
	 */
	private String buildDeleteQuery(Object[][] fieldsAndValues, String table){
		StringBuilder builder=new StringBuilder();
		builder.append("DELETE FROM "+table+" WHERE ");
		for(int i=0; i<fieldsAndValues.length; i++){
			if(i<fieldsAndValues.length-1){
				builder.append(fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"' AND ");
			}else{
				builder.append(fieldsAndValues[i][0]+"='"+fieldsAndValues[i][1]+"'");
			}
		}
		return builder.toString();
	}
	
	/**
	 * 
	 * Build the delete entry query
	 * 
	 * @param fieldsAndValues
	 * @param table
	 * @return
	 */
	public Boolean deleteEntry(Object[][] fieldsAndValues, String table){
		Boolean isSuccesful=false;
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			SQLQuery query=session.createSQLQuery(this.buildDeleteQuery(fieldsAndValues, table));
			int no_of_rows=query.executeUpdate();
			if(no_of_rows>0){
				isSuccesful=true;
			}
		}catch(HibernateException e){
			isSuccesful=false;
		}finally{
			session.close();
		}
		return isSuccesful;
	}
	
	
	/**
	 * 
	 * Update the patient table with the given information
	 * 
	 * @param patient
	 * @return isSuccess
	 */
	public Boolean update(Patient patient){
		Boolean isSuccessful=false;
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
		
			session.beginTransaction();
			Patient patient1=(Patient)session.get(Patient.class,patient.getPatientId());
			if(patient.getNicNo()==null){}else{patient1.setNicNo(patient.getNicNo());}
			if(patient.getPrefix()==null){}else{patient1.setPrefix(patient.getPrefix());}
			if(patient.getGivenName()==null){}else{patient1.setGivenName(patient.getGivenName());}
			if(patient.getFamilyName()==null){}else{patient1.setFamilyName(patient.getFamilyName());}
			if(patient.getNicNo()==null){}else{patient1.setNicNo(patient.getNicNo());}
			if(patient.getGender()==null){}else{patient1.setGender(patient.getGender());}
			if(patient.getBirthTime()==null){}else{patient1.setBirthTime(patient.getBirthTime());}
			if(patient.getBirthPlaceAddress()==null){}else{patient1.setBirthPlaceAddress(patient.getBirthPlaceAddress());}
			if(patient.getMultipleBirthIndex()==null){}else{patient1.setMultipleBirthIndex(patient.getMultipleBirthIndex());}
			if(patient.getMultipleBirthOrderNumber()==null){}else{patient1.setMultipleBirthOrderNumber(patient.getMultipleBirthOrderNumber());}
			if(patient.getOrganDonorIndex()==null){}else{patient1.setOrganDonorIndex(patient.getOrganDonorIndex());}
			if(patient.getMaritialStatus()==null){}else{patient1.setMaritialStatus(patient.getMaritialStatus());}
			if(patient.getEducationalLevelId()==null){}else{patient1.setEducationalLevelId(patient.getEducationalLevelId());}
			if(patient.getLivingArrangementId()==null){}else{patient1.setLivingArrangementId(patient.getLivingArrangementId());}
			if(patient.getReligiousAffliationId()==null){}else{patient1.setReligiousAffliationId((patient.getReligiousAffliationId()));}
			if(patient.getEthnicGroupId()==null){}else{patient1.setEthnicGroupId(patient.getEthnicGroupId());}
			if(patient.getConfidentialityLevelId()==null){}else{patient1.setConfidentialityLevelId(patient.getConfidentialityLevelId());}
			if(patient.getVeryImportantPatientId()==null){}else{patient1.setVeryImportantPatientId(patient.getVeryImportantPatientId());}
			if(patient.getDeceasedIndex()==null){}else{patient1.setDeceasedIndex(patient.getDeceasedIndex());}
			if(patient.getDeceasedTime()==null){}else{patient1.setDeceasedTime(patient.getDeceasedTime());}
			if(patient.getIsActive()==null){}else{patient1.setIsActive(patient.getIsActive());}
			session.update(patient1);
			session.getTransaction().commit();
			isSuccessful=true;
		
		return isSuccessful;
	}
	
	
	/**
	 * 
	 * Update the patient's email list
	 * 
	 * @param emailList
	 */
	public void updateEmailList(List<PatientEmail> emailList){
		for(int i=0;i<emailList.size();i++){
			Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
			
				session.beginTransaction();
				PatientEmail email=(PatientEmail)session.get(PatientEmail.class,emailList.get(i).getPatientEmailId());
				email.setPatientId(emailList.get(i).getPatientId());
				email.setEmail(emailList.get(i).getEmail());
				session.save(email);
				session.getTransaction().commit();
				
		}
	}
	
	
	/**
	 * 
	 * Update the patient's telephone list
	 * 
	 * @param telephoneList
	 */
	public void updateTelephoneList(List<PatientTelephone> telephoneList){
		for(int i=0;i<telephoneList.size();i++){
			Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
			
				session.beginTransaction();
				PatientTelephone telephone=(PatientTelephone)session.get(PatientTelephone.class,telephoneList.get(i).getPatientTelephoneNoId());
				telephone.setPatientId(telephoneList.get(i).getPatientId());
				telephone.setTelephoneNo(telephoneList.get(i).getTelephoneNo());
				session.save(telephone);
				session.getTransaction().commit();
				
		}
	}
	
	
	/**
	 * 
	 * Delete a patient from the system
	 * 
	 * @param patientId
	 * @return
	 */
	public boolean DeletePatient(int patientId){
		Boolean isSuccessful=false;
		Session session = PatientDetailsHibernateUtil.getSessionFactory().getCurrentSession();
		try{
			session.beginTransaction();
			Patient patient1=(Patient)session.get(Patient.class,patientId);
			patient1.setIsActive(false);
			session.update(patient1);
			session.getTransaction().commit();
			isSuccessful=true;
		}catch(HibernateException e){
			isSuccessful=false;
			throw e;
		}
		return isSuccessful;
	}

}
